package com.changjiang.tool.builder;

import com.changjiang.tool.config.PomText;
import com.changjiang.tool.exception.BuildException;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author : Chen Changjiang
 * @date : 2020/05/04
 * @description :
 */
public class MzzcModuleBuilder {

    private String projectLocation;
    private String newModuleName;

    private static final String FACADE_POSTFIX = "-facade";
    private static final String SERVICE_POSTFIX = "-service";
    private static final String WEB_POSTFIX = "-web";

    private static final String PACKAGE_NAME = "/com/jf/mzzc";


    public static void main(String[] args) {
        MzzcModuleBuilder mzzcModuleBuilder = new MzzcModuleBuilder("D://platform", "resource");
        mzzcModuleBuilder.buildMzzcMavenModule();
    }

    public MzzcModuleBuilder(String projectLocation, String newModuleName) {
        paramCheck(projectLocation, newModuleName);
        this.projectLocation = projectLocation;
        this.newModuleName = newModuleName;
    }

    /**
     * TODO 根据实际的异常情况进行参数检查-不断完善
     *
     * @param projectLocation 父工程路径
     * @param newModuleName   新模块名称
     */
    private void paramCheck(String projectLocation, String newModuleName) {
        if (newModuleName == null) {
            throw new BuildException("新模块名称不能为空");
        }
        File project = new File(projectLocation);
        if (!project.isDirectory()) {
            throw new BuildException(projectLocation + "-->文件夹不存在");
        }
        String projectPomLocation = projectLocation + "/pom.xml";
        File projectPomFile = new File(projectPomLocation);
        if (!projectPomFile.exists()) {
            throw new BuildException(projectLocation + "-->该位置不是一个maven结构的工程");
        }
    }

    /**
     * 1.在父目录中创建模块module
     * 2.创建子模块app(举例)与pom
     * 3.创建子模块下的app-facade,app-service,app-web的目录，具体maven结构目录，pom文件
     * 4.创建包，entity,facade,dao,daoImpl,service,facadeImpl,controller
     * 5.创建配置文件
     */
    public void buildMzzcMavenModule() {
        addModuleInFather();
        //在父工程目录下创建一个新模块（一级子模块）
        createSubProject();
        //建立子模块的子模块
        createDetailModule(FACADE_POSTFIX);
        createDetailModule(SERVICE_POSTFIX);
        createDetailModule(WEB_POSTFIX);
        //建立子模块下的具体文件包（相对比较特殊）
        createMVCPackage();
        //建立配置文件
        createPropertiesFile();
    }

    private void addModuleInFather() {
        String fatherPom = projectLocation + "/pom.xml";
        File pomFile = new File(fatherPom);
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(pomFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        MavenXpp3Reader reader = new MavenXpp3Reader();
        Model model = null;
        try {
            model = reader.read(inputStream);
        } catch (IOException | XmlPullParserException e) {
            e.printStackTrace();
        }
        List<String> modules = model.getModules();
        modules.add(newModuleName);
        model.setModules(modules);
        MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer();
        try {
            mavenXpp3Writer.write(new FileWriter(pomFile), model);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private String createDetailPackageName(String absolutePath, String detailPackage) {
        return absolutePath + PACKAGE_NAME + "/" + newModuleName + "/" + detailPackage;
    }

    private void createPropertiesFile() {
        String moduleLocation = projectLocation + "/" + newModuleName;
        String serviceLocation = moduleLocation + "/" + newModuleName + SERVICE_POSTFIX + "/src/main/resources";
        String webLocation = moduleLocation + "/" + newModuleName + WEB_POSTFIX + "/src/main/resources";
        try {
            new File(serviceLocation + "/application.properties").createNewFile();
            new File(webLocation + "/application.properties").createNewFile();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 具体的文件分组，包含dao,daoImpl,service,facade,facadeImpl,entity,controller，七个模块
     */
    private void createMVCPackage() {
        List<String> packageNames = new ArrayList<>();
        String moduleLocation = projectLocation + "/" + newModuleName;
        //在facade模块中创建entity,facade两个目录
        String facadeLocation = moduleLocation + "/" + newModuleName + FACADE_POSTFIX + "/src/main/java";
        packageNames.add(createDetailPackageName(facadeLocation, "facade"));
        packageNames.add(createDetailPackageName(facadeLocation, "entity"));
        //在service模块中创建dao,daoImpl,service,facadeImpl四个目录
        String serviceLocation = moduleLocation + "/" + newModuleName + SERVICE_POSTFIX + "/src/main/java";
        packageNames.add(createDetailPackageName(serviceLocation, "dao"));
        packageNames.add(createDetailPackageName(serviceLocation, "daoImpl"));
        packageNames.add(createDetailPackageName(serviceLocation, "service"));
        packageNames.add(createDetailPackageName(serviceLocation, "facadeImpl"));
        //在controller模块中创建controller目录
        String webLocation = moduleLocation + "/" + newModuleName + WEB_POSTFIX + "/src/main/java";
        packageNames.add(createDetailPackageName(webLocation, "controller"));
        buildDirectory(packageNames);
    }

    /**
     * 给定内容，创建文件
     *
     * @param fileName
     * @param text
     */
    private void createFileWithText(String fileName, String text) {
        File file = new File(fileName);
        if (file.exists()) {
            throw new BuildException("文件" + fileName + "已存在，创建有风险，请检查");
        }
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(text.getBytes());
            fileOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 在父工程目录下创建一个新模块（一级子模块） 如D://platform//app
     */
    private void createSubProject() {
        //1.创建子工程模块文件夹 如D://platform/app.如果模块存在，不创建，如果不存在则创建
        String modulePath = projectLocation + "/" + newModuleName;
        File moduleProject = new File(modulePath);
        buildModuleDirectory(moduleProject);
        //2.为模块创建pom
        createSubProjectPom();
    }

    /**
     * 一级子模块的pom文件
     */
    private void createSubProjectPom() {
        String fileName = projectLocation + "/" + newModuleName + "/pom.xml";
        String text = PomText.modulePomText.replace(PomText.modulePomReplacement, newModuleName);
        createFileWithText(fileName, text);
    }

    /**
     * 具体模块的pom文件
     *
     * @param postFix
     */
    private void createDetailModulePom(String postFix) {
        String detailModulePom = projectLocation + "/" + newModuleName + "/" + newModuleName + postFix + "/pom.xml";
        String text;
        if (FACADE_POSTFIX.equals(postFix)) {
            text = PomText.facadePomText.replace(PomText.facadePomReplacement, newModuleName);
        } else if (SERVICE_POSTFIX.equals(postFix)) {
            text = PomText.servicePomText.replace(PomText.servicePomReplacement, newModuleName);
        } else if (WEB_POSTFIX.equals(postFix)) {
            text = PomText.webPomText.replace(PomText.webPomReplacement, newModuleName);
        } else {
            throw new BuildException(postFix + "-该类型的后缀类型暂不支持");
        }
        createFileWithText(detailModulePom, text);
    }

    /**
     * 创建具体的模块，如D://platform//app内部的app-facade,app-service,app-web
     *
     * @param postFix 后缀，如"-facade"
     */
    private void createDetailModule(String postFix) {
        //1.创建模块文件夹-如果模块存在，不创建，如果不存在则创建
        String detailModulePath = projectLocation + "/" + newModuleName + "/" + newModuleName + postFix;
        File detailDirectory = new File(detailModulePath);
        buildModuleDirectory(detailDirectory);
        //创建具体的maven结构目录：main,test...
        buildMavenDirectory(detailModulePath);
        //2.为模块创建pom
        createDetailModulePom(postFix);
    }

    /**
     * 如果目录不存在则创建该目录；如果目录已存在，则抛出异常，该目录下无法创建
     *
     * @param moduleProject
     */
    private void buildModuleDirectory(File moduleProject) {
        if (moduleProject.exists()) {
            throw new BuildException(moduleProject.getAbsolutePath() + " 模块已存在，不可重复创建");
        }

        boolean mkdirs = moduleProject.mkdirs();
        if (!mkdirs) {
            throw new BuildException(moduleProject.getAbsolutePath() + " 创建目录失败");
        }
    }

    private void buildDirectory(List<String> fileNames) {
        for (String fileName : fileNames) {
            new File(fileName).mkdirs();
        }
    }

    private void buildMavenDirectory(String modulePath) {
        List<String> fileNames = new ArrayList<>();
        fileNames.add(modulePath + "/src/main/java");
        fileNames.add(modulePath + "/src/main/resources");
        fileNames.add(modulePath + "/src/test/java");
        fileNames.add(modulePath + "/src/test/resources");
        buildDirectory(fileNames);
    }

}
